package config.Interceptor;


import entity.Roleurl;
import entity.User;
import entity.UserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import service.impl.Userserviceimpl;
import utils.JwtUtils;
import utils.error.BusinessException;
import utils.error.EmBusinessError;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;

@Component
public class JwtAuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    Userserviceimpl userserviceimpl;

    @Autowired
    HttpServletRequest request;
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        // 从请求头中取出 token  这里需要和前端约定好把jwt放到请求头一个叫token的地方
        String token = httpServletRequest.getHeader("token");
//        System.out.println(token);
        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //检查是否有passtoken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //默认全部检查
        else {
            System.out.println("被jwt拦截需要验证");
            // 执行认证
            if (token == null) {
                //这里其实是登录失效,没token了
                throw new BusinessException(EmBusinessError.TOKEN_VERIFY_ERROR);
            }

            // 获取 token 中的 userName
            String userId = JwtUtils.getAudience(token);

            //找找看是否有这个user   因为我们需要检查用户是否存在
            User user = userserviceimpl.findeid(Integer.valueOf(userId));

            if (user == null) {
                //用户为空错误
                throw new BusinessException(EmBusinessError.USER_NOT_EXIST);
            }

            // 验证 token
            JwtUtils.verifyToken(token, userId);

            //获取载荷内容
            String userName = JwtUtils.getClaimByName(token, "userName").asString();
            String password = JwtUtils.getClaimByName(token,"password").asString();
            String roleId = JwtUtils.getClaimByName(token,"roleId").asString();

            //放入attribute以便后面调用
            httpServletRequest.setAttribute("userName", userName);
            httpServletRequest.setAttribute("password",password);
            httpServletRequest.setAttribute("roleId",roleId);

            //权限配置管理
            System.out.println("token验证成功");
            //获取权限列表
            List<UserRole> listroleid = userserviceimpl.listroleid();
            //获取登录接口用户权限id
            User userid = userserviceimpl.login(userName,password);

            //利用hash判断权限是否存在数据库中，有则继续执行，无则错误
            HashSet<Integer> set = new HashSet<Integer>();
            for (UserRole roleid: listroleid ) {
                set.add(Integer.parseInt(roleid.getRole_pid()));
            }
            boolean sesent = set.contains(userid.getRoleId());
            if (sesent)
            {
                System.out.println("该用户权限存在数据库中");
            }else {
                throw new BusinessException(EmBusinessError.ROLE_VERIFY_ERROR);
            }


            if (userid.getRoleId() == 1){
                System.out.println("该用户超级管理员权限");
                return true;
            }

            //检查是否存在Role，则验证该用户可以用的接口配置.
            if (method.isAnnotationPresent(Role.class)){
                Role role = method.getAnnotation(Role.class);
                //获取用户请求的url
                String url = request.getRequestURI();
                //获取权限表pid
                Roleurl rolepidall = userserviceimpl.urlpid(url);
                if (rolepidall == null)
                {
                    throw new BusinessException(EmBusinessError.ROLE_NOTURL_ERROR);
                }
                String[] rolepidsplit = rolepidall.getRole_pid().split(",");
                //先获取到访问url从权限数据表中获取到权限对应pid，然后对比用户访问该接口对应pid
                //有则访问，无则抛出异常
                HashSet<Integer> hashSetpid = new HashSet<Integer>();
                for (String rolepid: rolepidsplit) {
                    Integer integerrolepid = Integer.parseInt(rolepid);
                    hashSetpid.add(integerrolepid);
                }
                System.out.println(hashSetpid);
                boolean hashset = hashSetpid.contains(Integer.parseInt(roleId));
                System.out.println(hashset);
                if (hashset){
                    return true;
                }else {
                    throw new BusinessException(EmBusinessError.ROLE_DEFICIENCY_ERROR);
                }

            }else {
                throw new BusinessException(EmBusinessError.ROLE_NOTCONFIG_ERROR);
            }

        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
    }

}

